﻿using System.Collections.Generic;
using ApplicationLibrary;
using ApplicationLibrary.SqlConnector;
using Fighter.Masters.ModuleData;
using Fighter.Fights.ModuleData;
using System.Windows.Forms;
using Fighter.Fights.Libraries;
using Fighter.Fights.Reports.DataSet;
using System;
using System.Linq;
using System.Text.RegularExpressions;
using System.Drawing;

namespace Fighter.Fights.Reports
{
    public partial class FightCombinations : ApplicationLibrary.DBManager.ReportForm
    {
        private RRFight rRFight;
        private bool ElaborateEvents = true;
        private FightJoiner fJoiner = null;
        private DRAthlete drAthlete = null;
        private DSFights dsFight = null;
        private DRClub drClub = null;
        private TreeNode selectedNode; 

        public FightCombinations()
            : base("FightCombinations")
        {
            InitializeComponent();
        }

        protected override void OnBatchExecute(string reportName)
        {
            dsFight.Clear();

            RemoveEmptyNode(trvJoin.Nodes);
            AddAthleteFromTree(null, trvJoin.Nodes);
            ShowReport(new FightReport(), dsFight);

            if (!EnoughtOneSelect())
            {
                MessageBox.Show(Properties.Resources.Msg_NoFightSelect, Properties.Resources.M_Warning, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
        }


        private bool EnoughtOneSelect()
        {
            if (tsbAll.Checked)
                return true;

            for (int t = 0; t < clbFghts.Items.Count; t++)
                if (clbFghts.GetItemChecked(t))
                    return true;

            return false;
        }

        protected override void  OnAttachData()
        {
            rRFight = new RRFight();
            fJoiner = new FightJoiner();
            drAthlete = new DRAthlete();
            drClub = new DRClub();
            dsFight = new DSFights();
        }

        private bool LoadData()
        {
            dsFight.Clear();

            int fight = 0;
            if (rRFight.Find())
                fight = rRFight.GetValue<int>(FG_Fight.ID);

            QueryBuilder qb = new QueryBuilder(true);
            qb.SetQualified = true;

            qb.AddSelect();
            qb.AddFrom(FG_Registration.Name);

            SqlABParameter pFight = new SqlABParameter("@p1", FG_Registration.Fight);
            qb.AddCompare(FG_Registration.Fight, pFight);

            SqlABParameter pCheck = new SqlABParameter("@p2", FG_Registration.Checked);
            if (!tsbAlsoNotPresent.Checked)
            {
                qb.AddCompare(FG_Registration.Checked, pCheck);
                pCheck.Value = true;
            }

            if (!tsbAll.Checked)
                qb.Where += AddCompareFightColumn();

            pFight.Value = fight;

            using (SqlABCommand scc = new SqlABCommand(base.providerType, GlobalInfo.SqlConnection))
            {
                scc.CommandText = qb.Query;
                scc.Parameters.Add(pFight);
                if (!tsbAlsoNotPresent.Checked)
                    scc.Parameters.Add(pCheck);
                SqlABDataReader dr = scc.ExecuteReader();
                while (dr.Read())
                    AddRow(dr);
                dr.Close();
            }

            LoadTree();
            //ShowReport(new FightReport(), dsFight);
            return true;
        }

        private void LoadTree()
        {
            CreateTreeReport(true);
        }

        private void CreateTreeReport(bool CreateTree = false)
        {
            trvJoin.Nodes.Clear();
            foreach (KeyValuePair<string, Dictionary<string, Dictionary<int, Fight>>> kvpFight in fJoiner.FightJoin)
            {
                Dictionary<string, Dictionary<int, Fight>> kvpClub = kvpFight.Value;
                List<string> club = kvpClub.Keys.ToList();
                List<Dictionary<int, Fight>> match = kvpClub.Values.ToList();

                Fight[] at = new Fight[2];

                bool again = true;
                do
                {
                    again = false;
                    for (int cl = 0; cl < club.Count; cl++)
                    {
                        if (at[0] == null)
                        {
                            at[0] = GetMatch(match[cl]);
                            if (at[0] != null)
                            {
                                match[cl].Remove(at[0].IDAthlete);
                                again = true;
                            }
                            continue;
                        }

                        if (at[1] == null)
                        {
                            at[1] = GetMatch(match[cl]);
                            if (at[1] != null)
                            {
                                if (at[0].ClubMail == at[1].ClubMail)
                                {
                                    at[1] = null;
                                    continue;
                                }
                                match[cl].Remove(at[1].IDAthlete);
                                again = true;
                            }
                        }

                        if (at[0] != null && at[1] != null)
                        {
                            AddAthleteToTree(kvpFight.Key, at[0], at[1]);
                            at[0] = null;
                            at[1] = null;
                        }
                    }
                }
                while (again);
                if (at[0] != null)
                   AddAthleteToTree(kvpFight.Key, at[0], at[1]);

                do
                {
                    again = false;
                    for (int cl = 0; cl < club.Count; cl++)
                    {
                        at[0] = GetMatch(match[cl]);
                        if (at[0] != null)
                        {
                            AddAthleteToTree(kvpFight.Key, at[0], null);
                            match[cl].Remove(at[0].IDAthlete);
                            again = true;
                        }
                    }
                }
                while (again);
            }
        }

        private void AddAthleteToTree(string key, Fight at1, Fight at2)
        {
            TreeNode rootNode = null;
            Regex regex = new Regex(@"\[(.*?)\]");

            string[] tags = regex.Split(key);
            foreach (string tag in tags)
            {
                if (tag.IsEmpty())
                    continue;
                string[] single = tag.Split(new char[] {':'});

                switch (single[0])
                {
                    case "fight":
                        if (trvJoin.Nodes.ContainsKey(tag))
                            rootNode = trvJoin.Nodes[tag];
                        else
                        {
                            TreeNode node = trvJoin.Nodes.Add(DecodeFight(int.Parse(single[1])));
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "age":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(at1.AgeDesc);
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "belt":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(string.Format("Cintura {0}", DecodeBelt(single[1])));
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "class":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(string.Format("Classe {0}", single[1]));
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "series":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(string.Format("Serie {0}", single[1]));
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "gender":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(string.Format("Sesso {0}", single[1]));
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                    case "weight":
                        if (rootNode.Nodes.ContainsKey(tag))
                            rootNode = rootNode.Nodes[tag];
                        else
                        {
                            TreeNode node = rootNode.Nodes.Add(at1.WeightDesc);
                            node.Name = tag;
                            rootNode = node;
                        }
                        break;
                }
            }

            ExtendedTreeNode atNode = new ExtendedTreeNode(key, at1, at2);
            rootNode.Nodes.Add(atNode);
        }

        private void AddAthlete(List<Tokens> token, Fight at1, Fight at2)
        {
            int pos;
            int fight = -1;
            string age = "NULL";
            string level = "NULL";
            string weight = "NULL";
            string gender = "NULL";

            foreach (Tokens tk in token)
            {
                switch(tk.Token.Key())
                {
                    case "fight":
                        fight = tk.Token.ID();
                        DSFights.AggregatorRow aggr = dsFight.Aggregator.FindByFightID(tk.Token.ID());
                        if (aggr == null)
                        {
                            aggr = dsFight.Aggregator.NewAggregatorRow();
                            aggr.FightID = tk.Token.ID();
                            aggr.Description = tk.Description;
                            aggr.Evento = rRFight.GetValue<string>(FG_Fight.Description); ;
                            dsFight.Aggregator.AddAggregatorRow(aggr);
                        }
                        break;

                    case "age":
                        age = tk.Token.IDS();
                        DSFights.FightAgeRow ageRow = dsFight.FightAge.FindByFightIDAge(fight, age);
                        if (ageRow == null)
                        {
                            ageRow = dsFight.FightAge.NewFightAgeRow();
                            ageRow.FightID = fight;
                            ageRow.Age = age;

                            ageRow.Description = age == "NULL"
                                                    ? string.Empty
                                                    : tk.Description;
                            dsFight.FightAge.AddFightAgeRow(ageRow);
                        }
                        break;
                    case "belt":
                            level = tk.Token.IDS();

                            DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, fight);
                            if (levelRow == null)
                            {
                                levelRow = dsFight.FightLevel.NewFightLevelRow();
                                levelRow.Text = "Cintura";
                                levelRow.FightID = fight;
                                levelRow.Age = age;
                                levelRow.BeltLevSer = level;
                                levelRow.Description = level == "NULL"
                                                        ? string.Empty
                                                        : tk.Description;
                                dsFight.FightLevel.AddFightLevelRow(levelRow);
                            }
                        break;
                    case "class":
                            level = tk.Token.IDS();
                            DSFights.FightLevelRow classRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, fight);
                            if (classRow == null)
                            {
                                classRow = dsFight.FightLevel.NewFightLevelRow();
                                classRow.Text = "Classe";
                                classRow.FightID = fight;
                                classRow.Age = age;
                                classRow.BeltLevSer = level;
                                classRow.Description = level == "NULL"
                                                        ? string.Empty
                                                        : tk.Token.IDS();
                                dsFight.FightLevel.AddFightLevelRow(classRow);
                            }
                        break;
                    case "series":
                            level = tk.Token.IDS();
                            DSFights.FightLevelRow seriesRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, fight);
                            if (seriesRow == null)
                            {
                                seriesRow = dsFight.FightLevel.NewFightLevelRow();
                                seriesRow.Text = "Serie";
                                seriesRow.FightID = fight;
                                seriesRow.Age = age;
                                seriesRow.BeltLevSer = level;
                                seriesRow.Description = level == "NULL"
                                                        ? string.Empty
                                                        : tk.Token.IDS(); ;
                                dsFight.FightLevel.AddFightLevelRow(seriesRow);
                            }
                        break;
                    case "gender":
                        gender = tk.Token.IDS();
                        break;
                    case "weight":
                        weight = tk.Token.IDS();
                            DSFights.FightWeightRow weightRow = dsFight.FightWeight.FindByWeightBeltLevSerAgeFightID(weight, level, age, fight);
                            if (weightRow == null)
                            {
                                weightRow = dsFight.FightWeight.NewFightWeightRow();
                                weightRow.FightID = fight;
                                weightRow.Age = age;
                                weightRow.BeltLevSer = level;
                                weightRow.Weight = weight;
                                weightRow.Description = weight == "NULL"
                                                        ? string.Empty
                                                        : tk.Description;
                                weightRow.Gender = gender == "M"
                                                    ? "Uomini"
                                                    : "Donne";
                                dsFight.FightWeight.AddFightWeightRow(weightRow);
                            }
                        break;
                }




                //#region Age
                //token = tk.Token.Key("age");
                //if (!token.IsEmpty())
                //    age = token;


                //#endregion
                //#region Belt
                //token = key.Key("belt");
                //if (!token.IsEmpty())
                //{
                //    level = token;

                //    DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, aggr.FightID);
                //    if (levelRow == null)
                //    {
                //        levelRow = dsFight.FightLevel.NewFightLevelRow();
                //        levelRow.Text = "Cintura";
                //        levelRow.FightID = aggr.FightID;
                //        levelRow.Age = ageRow.Age;
                //        levelRow.BeltLevSer = level;
                //        levelRow.Description = level == "NULL"
                //                                ? string.Empty
                //                                : DecodeBelt(token);
                //        dsFight.FightLevel.AddFightLevelRow(levelRow);
                //    }
                //}
                //#endregion
                //#region Class
                //token = key.Key("class");
                //if (!token.IsEmpty())
                //{
                //    level = token;

                //    DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, aggr.FightID);
                //    if (levelRow == null)
                //    {
                //        levelRow = dsFight.FightLevel.NewFightLevelRow();
                //        levelRow.Text = "Classe";
                //        levelRow.FightID = aggr.FightID;
                //        levelRow.Age = ageRow.Age;
                //        levelRow.BeltLevSer = level;
                //        levelRow.Description = level == "NULL"
                //                                ? string.Empty
                //                                : token;
                //        dsFight.FightLevel.AddFightLevelRow(levelRow);
                //    }
                //}
                //#endregion
                //#region Series
                //token = key.Key("series");
                //if (!token.IsEmpty())
                //{
                //    level = token;
                //    DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, aggr.FightID);
                //    if (levelRow == null)
                //    {
                //        levelRow = dsFight.FightLevel.NewFightLevelRow();
                //        levelRow.Text = "Serie";
                //        levelRow.FightID = aggr.FightID;
                //        levelRow.Age = ageRow.Age;
                //        levelRow.BeltLevSer = level;
                //        levelRow.Description = level == "NULL"
                //                                ? string.Empty
                //                                : token;
                //        dsFight.FightLevel.AddFightLevelRow(levelRow);
                //    }
                //}
                //#endregion
                //if (level == "NULL")
                //{
                //    DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, aggr.FightID);
                //    if (levelRow == null)
                //    {
                //        levelRow = dsFight.FightLevel.NewFightLevelRow();
                //        levelRow.FightID = aggr.FightID;
                //        levelRow.Age = ageRow.Age;
                //        levelRow.BeltLevSer = level;
                //        levelRow.Description = string.Empty;
                //        dsFight.FightLevel.AddFightLevelRow(levelRow);
                //    }
                //}

                //#region Weight
                //pos = key.IndexOf("[gender:");
                //if (pos != 0)
                //    gender = key.Substring(pos + 8, 1);

                //pos = key.IndexOf("[weight:");
                //if (pos > 0)
                //{
                //    weight = key.Substring(pos + 8, 3);
                //    DSFights.FightWeightRow weightRow = dsFight.FightWeight.FindByWeightBeltLevSerAgeFightID(weight, level, age, aggr.FightID);
                //    if (weightRow == null)
                //    {
                //        weightRow = dsFight.FightWeight.NewFightWeightRow();
                //        weightRow.FightID = aggr.FightID;
                //        weightRow.Age = ageRow.Age;
                //        weightRow.BeltLevSer = level;
                //        weightRow.Weight = weight;
                //        weightRow.Description = weight == "NULL"
                //                                ? string.Empty
                //                                : at1.WeightDesc;
                //        weightRow.Gender = gender == "M"
                //                            ? "Uomini"
                //                            : "Donne";
                //        dsFight.FightWeight.AddFightWeightRow(weightRow);
                //    }
                //}
                //#endregion
                //#region Details
                //DSFights.FightDetailRow fightDetailRow = dsFight.FightDetail.NewFightDetailRow();
                //fightDetailRow.FightID = aggr.FightID;
                //fightDetailRow.Age = age;
                //fightDetailRow.BeltLevSer = level;
                //fightDetailRow.Weight = weight;
                //fightDetailRow.Bullet = at2 == null
                //                            ? "m"
                //                            : "l";

                //fightDetailRow.Club1 = drClub.Find(at1.ClubMail)
                //                            ? drClub.GetValue<string>(FG_Club.Club)
                //                            : at1.ClubMail;

                //fightDetailRow.Athlete1 = drAthlete.Find(at1.IDAthlete)
                //                            ? drAthlete.GetValue<string>(FG_Athlete.FirstName)
                //                            : at1.IDAthlete.ToString();

                //fightDetailRow.Club2 = at2 == null || !drClub.Find(at2.ClubMail)
                //                        ? "" :
                //                        drClub.GetValue<string>(FG_Club.Club);

                //fightDetailRow.Athlete2 = at2 == null || !drAthlete.Find(at2.IDAthlete)
                //                            ? "" :
                //                            drAthlete.GetValue<string>(FG_Athlete.FirstName);
                //dsFight.FightDetail.AddFightDetailRow(fightDetailRow);
                //#endregion
            }
            if (level == "NULL")
            {
                DSFights.FightLevelRow levelRow = dsFight.FightLevel.FindByBeltLevSerAgeFightID(level, age, fight);
                if (levelRow == null)
                {
                    levelRow = dsFight.FightLevel.NewFightLevelRow();
                    levelRow.FightID = fight;
                    levelRow.Age = age;
                    levelRow.BeltLevSer = level;
                    levelRow.Description = string.Empty;
                    dsFight.FightLevel.AddFightLevelRow(levelRow);
                }
            }

            DSFights.FightDetailRow fightDetailRow = dsFight.FightDetail.NewFightDetailRow();
            fightDetailRow.FightID = fight;
            fightDetailRow.Age = age;
            fightDetailRow.BeltLevSer = level;
            fightDetailRow.Weight = weight;
            fightDetailRow.Bullet = at2 == null
                                        ? "m"
                                        : "l";

            fightDetailRow.Club1 = drClub.Find(at1.ClubMail)
                                        ? drClub.GetValue<string>(FG_Club.Club)
                                        : at1.ClubMail;

            fightDetailRow.Athlete1 = drAthlete.Find(at1.IDAthlete)
                                        ? drAthlete.GetValue<string>(FG_Athlete.FirstName)
                                        : at1.IDAthlete.ToString();

            fightDetailRow.Club2 = at2 == null || !drClub.Find(at2.ClubMail)
                                    ? "" :
                                    drClub.GetValue<string>(FG_Club.Club);

            fightDetailRow.Athlete2 = at2 == null || !drAthlete.Find(at2.IDAthlete)
                                        ? "" :
                                        drAthlete.GetValue<string>(FG_Athlete.FirstName);
            dsFight.FightDetail.AddFightDetailRow(fightDetailRow);
        }

        private string DecodeFight(int fight)
        {
            return clbFghts.Items[fight-1].ToString();
        }

        private string DecodeBelt(string belt)
        {
            switch(belt)
            {
                case "01":
                    return "Gialla Arancione Verde";
                case "02":
                    return "Marrone Blue Nera";
                default:
                    return string.Empty;
            }
            
        }

        private Fight GetMatch(Dictionary<int, Fight> match)
        {
            Fight mt = null;
            List<int> keys = match.Keys.ToList<int>();
            if (keys.Count > 0)
            {
                mt = new Fight();
                mt = match[keys[0]];
            }

            return mt;
        }

        private void AddRow(SqlABDataReader dr)
        {
            string key = string.Empty;
            string club = dr.GetValue<string>(FG_Registration.Mail);
            int athlete = dr.GetValue<int>(FG_Registration.Athlete);
            
            if (!drAthlete.Find(athlete))
            {
                MessageBox.Show(string.Format(Properties.Resources.Msg_AthleteNotFound, dr.GetValue<int>(FG_Registration.Athlete), dr.GetValue<string>(FG_Registration.Mail)), Properties.Resources.M_Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Leggo i dati dell'Atleta
            int age = CalculateAge(drAthlete.GetValue<DateTime>(FG_Athlete.BirthDay), GlobalInfo.CurrentDate);
            Gender gender = drAthlete.GetValue<Gender>(FG_Athlete.Gender);
            double weight = drAthlete.GetValue<double>(FG_Athlete.Weight);
            Belts belt = drAthlete.GetValue<Belts>(FG_Athlete.Belt);
            string grapLevel = drAthlete.GetValue<string>(FG_Athlete.GrapLevel);
            int fContMatch = drAthlete.GetValue<int>(FG_Athlete.FContMatch);
            int lKickMatch = drAthlete.GetValue<int>(FG_Athlete.LKickMatch);
            int k1RulMatch = drAthlete.GetValue<int>(FG_Athlete.K1RulMatch);

            if (dr.GetValue<bool>(FG_Registration.ChausLight) && (tsbAll.Checked || ReadCheckBox("Chauss Fight Assalto")))
                fJoiner.AddFight(club, athlete, 1, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.SavateAss) && (tsbAll.Checked || ReadCheckBox("Savate Assalto")))
                fJoiner.AddFight(club, athlete, 2, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.PointFight) && (tsbAll.Checked || ReadCheckBox("Free Punch Light")))
                fJoiner.AddFight(club, athlete, 3, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.LightContact) && (tsbAll.Checked || ReadCheckBox("Light Contact")))
                fJoiner.AddFight(club, athlete, 4, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.KickLight) && (tsbAll.Checked || ReadCheckBox("Kick Light")))
                fJoiner.AddFight(club, athlete, 5, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.K1Light) && (tsbAll.Checked || ReadCheckBox("K1 Light")))
                fJoiner.AddFight(club, athlete, 6, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.ThaiLight) && (tsbAll.Checked || ReadCheckBox("Thai Light")))
                fJoiner.AddFight(club, athlete, 7, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.MmaLight) && (tsbAll.Checked || ReadCheckBox("MMA Light")))
                fJoiner.AddFight(club, athlete, 8, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.Grapling) && (tsbAll.Checked || ReadCheckBox("Grappling")))
                fJoiner.AddFight(club, athlete, 9, age, gender, weight, belt, 0, grapLevel);

            if (dr.GetValue<bool>(FG_Registration.ChaussCombact) && (tsbAll.Checked || ReadCheckBox("Chauss Fight Combat")))
                fJoiner.AddFight(club, athlete, 10, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.SavateCombact) && (tsbAll.Checked || ReadCheckBox("Savate Combat")))
                fJoiner.AddFight(club, athlete, 11, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.FullContact) && (tsbAll.Checked || ReadCheckBox("Free Punch")))
                fJoiner.AddFight(club, athlete, 12, age, gender, weight, belt, fContMatch);

            if (dr.GetValue<bool>(FG_Registration.LowKick) && (tsbAll.Checked || ReadCheckBox("Low Kick")))
                fJoiner.AddFight(club, athlete, 13, age, gender, weight, belt, lKickMatch);

            if (dr.GetValue<bool>(FG_Registration.K1Rules) && (tsbAll.Checked || ReadCheckBox("K1 Rules")))
                fJoiner.AddFight(club, athlete, 14, age, gender, weight, belt, k1RulMatch);

            if (dr.GetValue<bool>(FG_Registration.ThaiFull) && (tsbAll.Checked || ReadCheckBox("Thai Full Rules")))
                fJoiner.AddFight(club, athlete, 15, age, gender, weight, belt);

            if (dr.GetValue<bool>(FG_Registration.MMAFull ) && (tsbAll.Checked || ReadCheckBox("MMA Full Rules")))
                fJoiner.AddFight(club, athlete, 16, age, gender, weight, belt);
        }

        private string AddCompareFightColumn()
        {
            QueryBuilder qb = new QueryBuilder();
            qb.AND_OR = "OR";

            if (ReadCheckBox("Chauss Fight Assalto"))
                qb.AddCompare<bool>(FG_Registration.ChausLight, true);

            if (ReadCheckBox("Savate Assalto"))
                qb.AddCompare<bool>(FG_Registration.SavateAss, true);

            if (ReadCheckBox("Free Punch Light"))
                qb.AddCompare<bool>(FG_Registration.PointFight, true);

            if (ReadCheckBox("Light Contact"))
                qb.AddCompare<bool>(FG_Registration.LightContact, true);

            if (ReadCheckBox("Kick Light"))
                qb.AddCompare<bool>(FG_Registration.KickLight, true);

            if (ReadCheckBox("K1 Light"))
                qb.AddCompare<bool>(FG_Registration.K1Light, true);

            if (ReadCheckBox("Thai Light"))
                qb.AddCompare<bool>(FG_Registration.ThaiLight, true);

            if (ReadCheckBox("MMA Light"))
                qb.AddCompare<bool>(FG_Registration.MmaLight, true);

            if (ReadCheckBox("Grappling"))
                qb.AddCompare<bool>(FG_Registration.Grapling, true);

            if (ReadCheckBox("Chauss Fight Combat"))
                qb.AddCompare<bool>(FG_Registration.ChaussCombact, true);

            if (ReadCheckBox("Savate Combat"))
                qb.AddCompare<bool>(FG_Registration.SavateCombact, true);

            if (ReadCheckBox("Free Punch"))
                qb.AddCompare<bool>(FG_Registration.FullContact, true);

            if (ReadCheckBox("Low Kick"))
                qb.AddCompare<bool>(FG_Registration.LowKick, true);

            if (ReadCheckBox("K1 Rules"))
                qb.AddCompare<bool>(FG_Registration.K1Rules, true);

            if (ReadCheckBox("Thai Full Rules"))
                qb.AddCompare<bool>(FG_Registration.ThaiFull, true);

            if (ReadCheckBox("MMA Full Rules"))
                qb.AddCompare<bool>(FG_Registration.MMAFull, true);
                
            return qb.Where.IsEmpty()
                       ? ""
                       :string.Format(" AND ({0})", qb.Where);
        }


        private bool ReadCheckBox(string fight)
        {
            for (int t = 0; t < clbFghts.Items.Count; t++)
                if (clbFghts.GetItemText(clbFghts.Items[t]) == fight)
                    return clbFghts.GetItemChecked(t);

            System.Diagnostics.Debug.Assert(false);
            return true;
        }

        private void clbFghts_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (ElaborateEvents)
            {
                ElaborateEvents = false;
                if (e.NewValue == CheckState.Checked)
                {
                    tsbAll.Checked = false;

                }
                else
                {
                    bool OneSelect = false;
                    for (int t = 0; t < clbFghts.Items.Count; t++)
                        if (t != e.Index)
                            OneSelect |= clbFghts.GetItemChecked(t);

                    tsbAll.Checked = !OneSelect;
                }
                ElaborateEvents = true;
            }
        }

        public int CalculateAge(DateTime birthDate, DateTime now)
        {
            int age = now.Year - birthDate.Year;
            if (now.Month < birthDate.Month || (now.Month == birthDate.Month && now.Day < birthDate.Day)) age--;
            return age;
        }

        private void tsbElaborate_Click(object sender, EventArgs e)
        {
            if (!LoadData())
            {
                MessageBox.Show(Properties.Resources.Msg_NoDataFound, Properties.Resources.M_Warning, MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
        }

        private void trvJoin_DragEnter(object sender, DragEventArgs e)
        {
            Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
            var node = ((TreeView)sender).GetNodeAt(pt);
            if (node != null && node.GetType() == typeof(ExtendedTreeNode))
            {
                ExtendedTreeNode sourceNode = ((TreeView)sender).GetNodeAt(pt) as ExtendedTreeNode;
                e.Effect = sourceNode.Fighter2 == null
                                ? DragDropEffects.Move
                                : DragDropEffects.None;

                System.Diagnostics.Debug.WriteLine(e.Effect);
            }
        }

        private void trvJoin_ItemDrag(object sender, ItemDragEventArgs e)
        {
            DoDragDrop(e.Item, DragDropEffects.Move);
            System.Diagnostics.Debug.WriteLine(e.Item.ToString());
        }

        private void trvJoin_DragDrop(object sender, DragEventArgs e)
        {
            ExtendedTreeNode originalNode;

            if (e.Data.GetDataPresent("Fighter.Fights.Libraries.ExtendedTreeNode", false))
            {
                Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                originalNode = (ExtendedTreeNode)e.Data.GetData("Fighter.Fights.Libraries.ExtendedTreeNode");

                var node = ((TreeView)sender).GetNodeAt(pt);
                if (node != null && node.GetType() == typeof(ExtendedTreeNode))
                {
                    ExtendedTreeNode DestinationNode = node as ExtendedTreeNode;

                    DestinationNode.AddFighter(originalNode.Fighter1);
                    DestinationNode.Expand();
                    originalNode.Remove();
                }
                else
                {
                    TreeNode DestinationNode = node as TreeNode;
                    DestinationNode.Nodes.Add((ExtendedTreeNode)originalNode.Clone());
                    DestinationNode.Expand();
                    originalNode.Remove();
                }

            }
        }
        private void trvJoin_DragOver(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent("Fighter.Fights.Libraries.ExtendedTreeNode", false))
            {
                Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
                ExtendedTreeNode originalNode = (ExtendedTreeNode)e.Data.GetData("Fighter.Fights.Libraries.ExtendedTreeNode");
                var node = ((TreeView)sender).GetNodeAt(pt);
                if (node != null && node.GetType() == typeof(ExtendedTreeNode))
                {
                    ExtendedTreeNode destNode = ((TreeView)sender).GetNodeAt(pt) as ExtendedTreeNode;
                    e.Effect = destNode.Fighter2 == null && destNode.Fighter1 != originalNode.Fighter1
                                    ? DragDropEffects.Move
                                    : DragDropEffects.None;
                }
                else
                    e.Effect = DragDropEffects.Move;
            }
        }

        private void tsbExpand_Click(object sender, EventArgs e)
        {
            trvJoin.ExpandAll();
        }

        private void trvJoin_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button != System.Windows.Forms.MouseButtons.Right)
                return;

            var node = ((TreeView)sender).GetNodeAt(e.X, e.Y);
            Point pt = new Point(e.X, e.Y);

            if (node != null)
            {
                if (node.GetType() == typeof(ExtendedTreeNode))
                {
                    ExtendedTreeNode destNode = ((TreeView)sender).GetNodeAt(pt) as ExtendedTreeNode;
                    cmsSplit.Show((TreeView)sender, pt);
                }
                else
                {
                    if (node.Name != null && node.Name.ToString().StartsWith("fight:"))
                        cmsPrint.Show((TreeView)sender, pt);
                    if (node.Name != null && node.Name.ToString().StartsWith("weight:"))
                        cmsAdd.Show((TreeView)sender, pt);
                }
            }

        }

        private void cmsSplit_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch(e.ClickedItem.Name)
            {
                case "tsmiSplitAthletes":
                    SplitAthlete();
                    break;
                case "tsmiDeleteAthlete":
                    if (MessageBox.Show(this, "Sei sicuro di rimuovere l'atleta ?", "Cancellazione atleta", MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == System.Windows.Forms.DialogResult.Yes)
                        DeleteAthlete();

                    break;
                case "tsmiAthlete1":
                    OpenMaster(((ExtendedTreeNode)selectedNode).Fighter1);
                    break;
                case "tsmiAthlete2":
                    if (!e.ClickedItem.Text.TrimAll().IsEmpty())
                        OpenMaster(((ExtendedTreeNode)selectedNode).Fighter2);

                    break;
            }

        }

        private void cmsAdd_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            using(RadarAthlete rdr = new RadarAthlete())
            {
                rdr.RadarFormRowSelected+=new ApplicationLibrary.ExtendedControls.RadarForm.RadarFormRowSelectedEventHandler(rdr_RadarFormRowSelected);
                rdr.ShowDialog();
            }

        }

        void rdr_RadarFormRowSelected(object sender, ApplicationLibrary.ExtendedControls.RadarFormRowSelectedArgs pe)
        {
            var athlete = (int) pe.parameters[0];
            var f1 = CreateFightFromAthlete(athlete);
            ExtendedTreeNode exTree = new ExtendedTreeNode("", f1, null);
            selectedNode.Nodes.Add(exTree);
        }

        private Fight CreateFightFromAthlete(int athlete)
        {
            drAthlete.Find(athlete);
            var f = new Fight();
            f.IDAthlete = athlete;
            f.ClubMail = drAthlete.GetValue<string>(FG_Athlete.Mail);
            f.Age = CalculateAge(drAthlete.GetValue<DateTime>(FG_Athlete.BirthDay), GlobalInfo.CurrentDate);
            f.Gender = drAthlete.GetValue<Gender>(FG_Athlete.Gender);
            f.Weight = drAthlete.GetValue<double>(FG_Athlete.Weight);
            f.Belt = drAthlete.GetValue<Belts>(FG_Athlete.Belt);
            return f;
        }

        private void DeleteAthlete()
        {
            TreeNode parent = selectedNode.Parent;
            ExtendedTreeNode f1 = selectedNode as ExtendedTreeNode;
            parent.Nodes.Remove(f1);
        }

        private void OpenMaster(Fight fight)
        {
            Fighter.Masters.Forms.Athlete frm = (Fighter.Masters.Forms.Athlete)GlobalInfo.OpenForm("Fighter.Fighter.Masters.Forms.Athlete", false);
            frm.FindRecord(new RadarAthleteParam(fight.IDAthlete));
        }

        private void SplitAthlete()
        {
            TreeNode parent = selectedNode.Parent;
            ExtendedTreeNode f2 = (ExtendedTreeNode)selectedNode.Clone();
            ExtendedTreeNode f1 = selectedNode as ExtendedTreeNode;
            f2.RemoveFighter1();
            f1.RemoveFighter2();
            parent.Nodes.Add(f2);
        }

        private void cmsRename_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (!selectedNode.IsEditing)
            {
                selectedNode.BeginEdit();
            }
        }

        private void trvJoin_MouseDown(object sender, MouseEventArgs e)
        {
            selectedNode = trvJoin.GetNodeAt(e.X, e.Y);
            if (selectedNode != null)
            {
                trvJoin.SelectedNode = selectedNode;
                trvJoin.LabelEdit = trvJoin.GetNodeAt(e.X, e.Y).GetType() == typeof(TreeNode);
                if (!trvJoin.LabelEdit)
                {
                    ExtendedTreeNode exTreeNode = selectedNode as ExtendedTreeNode;
                    tsmiAthlete1.Text = drAthlete.Find(exTreeNode.Fighter1.IDAthlete)
                            ? drAthlete.GetValue<string>(FG_Athlete.FirstName)
                            : exTreeNode.Fighter1.IDAthlete.ToString();
                    tsmiAthlete2.Enabled = exTreeNode.Fighter2 != null;
                    tsmiSplitAthletes.Enabled = exTreeNode.Fighter2 != null;
                    tsmiDeleteAthlete.Enabled = exTreeNode.Fighter2 == null || exTreeNode.Fighter1 == null;
                    if (exTreeNode.Fighter2 != null)
                        tsmiAthlete2.Text = drAthlete.Find(exTreeNode.Fighter2.IDAthlete)
                                ? drAthlete.GetValue<string>(FG_Athlete.FirstName)
                                : exTreeNode.Fighter2.IDAthlete.ToString();
                    else
                        tsmiAthlete2.Text = string.Empty;
                }
            }

        }

        private void trvJoin_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.F2 && selectedNode != null && !selectedNode.IsEditing)
                    selectedNode.BeginEdit();
        }

        private void RemoveEmptyNode(TreeNodeCollection nodes)
        {
            for (int t = nodes.Count - 1; t>=0;t--)
            {
                RemoveEmptyNode(nodes[t].Nodes);
                if (nodes[t].Nodes.Count == 0 && nodes[t].GetType() == typeof(TreeNode))
                    nodes[t].Remove();
            }
        }

        private void RemoveEmptyNode(TreeNode node)
        {
                RemoveEmptyNode(node.Nodes);
                if (node.Nodes.Count == 0 && node.GetType() == typeof(TreeNode))
                    node.Remove();
        }

        private void AddAthleteFromTreeNode(List<Tokens> key, TreeNode nd)
        {
            if (nd.GetType() == typeof(TreeNode))
            {
                if (key == null)
                    key = new List<Tokens>();
                if (nd.Name.Key() == "fight")
                    key.Clear();
                key.Add(new Tokens(nd.Name, nd.Text));
                AddAthleteFromTree(key, nd.Nodes);
            }
        }

        private void AddAthleteFromTree(List<Tokens> key, TreeNodeCollection nodes)
        {
            foreach (TreeNode nd in nodes)
            {
                if (nd.GetType() == typeof(TreeNode))
                {
                    if (key == null)
                        key = new List<Tokens>();
                    if (nd.Name.Key() == "fight")
                        key.Clear();
                    key.Add(new Tokens(nd.Name, nd.Text));
                    AddAthleteFromTree(key, nd.Nodes);
                }
                else
                {
                    ExtendedTreeNode extNode = nd as ExtendedTreeNode;
                    AddAthlete(key, extNode.Fighter1, extNode.Fighter2);
                }
            }
        }

        private string CreateNewKey(string key, string tag, TreeNode treeNode)
        {
            // @TODO
            Regex rEx = new Regex(@"(.*?):");
            Match mc = rEx.Match(tag);
            if (mc.Success)
            {
                if (tag == "age:" || tag == "belt:")
                return string.Concat("[" + mc.Value + treeNode.Text + "]");
            }
            return string.Concat(key, "[", tag, "]");
        }

        private void tsbAll_Click(object sender, EventArgs e)
        {
            if (ElaborateEvents)
            {
                ElaborateEvents = false;
                if (tsbAll.Checked)
                {
                    for (int t = 0; t < clbFghts.Items.Count; t++)
                        clbFghts.SetItemChecked(t, false);
                }
                ElaborateEvents = true;
            }
        }

        private void cmsPrint_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch (e.ClickedItem.Name)
            {
                case "tsmiPrint":
                    PrintFromHere();
                    break;
                case "tsmiExpand":
                    ExpandFromHere();
                    break;
            }

        }
    
        private void ExpandFromHere()
        {
            trvJoin.SelectedNode.ExpandAll();
        }

        private void PrintFromHere()
        {
            dsFight.Clear();

            RemoveEmptyNode(trvJoin.SelectedNode);
            AddAthleteFromTreeNode(null, trvJoin.SelectedNode);
            ShowReport(new FightReport(), dsFight);
        }

        private void tsbSave_Click(object sender, EventArgs e)
        {
            if (sfdSave.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                TreeViewSerializer.TreeViewToXml(trvJoin, sfdSave.FileName);
        }

        private void FightCombinations_Load(object sender, EventArgs e)
        {
        }

        private void tsbLoad_Click(object sender, EventArgs e)
        {
            rRFight.Find();
            if (ofdLoad.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                TreeViewSerializer.XmlToTreeView(ofdLoad.FileName, trvJoin);
        }
    }

    public static class ReturnKey
    {
        public static string Value(this string val, string token)
        {
            string pattern = string.Format("\\[{0}:(.*?)\\]", token);

           // (@"\[(.*?)\]");

            try
            {
                Match match = Regex.Match(val, pattern, RegexOptions.IgnoreCase);
                if (match.Success)
                    return match.Value.Substring(match.Value.IndexOf(':') + 1).TrimEnd(new char[] { ']', '}' });
                else
                    return string.Empty;
            }
            catch (Exception e)
            {
                return string.Empty;
            }
            finally
            {
                
            }

        }
        public static string Key(this string val)
        {
            return val.Substring(0, val.IndexOf(':'));
        }

        public static int ID(this string val)
        {
            return int.Parse(val.Substring(val.IndexOf(':')+1));
        }
        public static string IDS(this string val)
        {
            return val.Substring(val.IndexOf(':') + 1);
        }
    }

    internal class Tokens
    {
        public string Token {get; private set;}
        public string Description{get; private set;}

        public Tokens(string token, string description)
        {
            Token = token;
            Description = description;
        }
    }


}
